package com.baofu.paycore.biz.paycore.handler.impl;

import com.baofu.account.service.facade.model.request.FreezeReqDTO;
import com.baofu.clear.service.facade.model.resp.NotifyDTO;
import com.baofu.paycore.biz.engine.result.CommandResult;
import com.baofu.paycore.biz.external.account.AccountService;
import com.baofu.paycore.biz.external.account.converter.AccountRequestConverter;
import com.baofu.paycore.biz.model.BackPayBO;
import com.baofu.paycore.biz.paycore.converter.BO2BOConverter;
import com.baofu.paycore.biz.paycore.handler.BaseHandler;
import com.baofu.paycore.common.exception.PayCoreBizException;
import com.baofu.paycore.manager.model.AccountRespBO;
import com.baofu.paycore.manager.model.FreezeBO;
import com.baofu.paycore.manager.model.ResponseBO;
import com.baofu.paycore.manager.model.preAuth.PreAuthBO;
import com.baofu.paycore.manager.storer.FreezeOrderRepository;
import com.baofu.paycore.service.facade.enums.PayCoreErrorCode;
import com.baofu.paycore.service.facade.enums.PayStatusEnums;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;

/**
 * <p>
 * </p>
 * User:ames wang  Date: 2017/6/22
 */
@Slf4j
@Service
public class FreezeHandler extends BaseHandler<FreezeBO,NotifyDTO> {

    /**
     * 账务转账服务
     */
    @Autowired
    private AccountService accountService;

    @Autowired
    private FreezeOrderRepository freezeOrderRepository;

    @Override
    public FreezeBO activeOrder(String orderId) {
        FreezeBO freezeBO = freezeOrderRepository.load(orderId);
        if(freezeBO == null){
            log.error("找不到冻结订单:{}",orderId);
            throw new PayCoreBizException(PayCoreErrorCode.ORDER_IS_NOT_EXISTED);
        }
        return freezeBO;
    }

    @Override
    public FreezeBO queryOrderByPayNo(String payNo) {
        return activeOrder(payNo);
    }

    @Override
    protected void checkBeforeProcess(FreezeBO order) {

    }

    @Override
    protected void processOrders(FreezeBO order) {
        //冻结账务
        accountFreeze(order);
        order.setRealFlag(true);
    }

    @Override
    protected void reStore(FreezeBO order) {
        freezeOrderRepository.update(order);
    }

    @Override
    protected void processAfter(FreezeBO order, Map<String, CommandResult> cmdResult) {

    }

    /**
     * 提现处理
     *
     * @param freezeBO    提现参数
     * @return              返回值
     */
    @Override
    public BackPayBO process(FreezeBO freezeBO) {
        log.debug("冻结开始处理：{}", freezeBO);
        doExecute(freezeBO);
        log.info("冻结完成结果：{}",freezeBO);
        return BO2BOConverter.freezeBO2BackPayBO(freezeBO);
    }

    /**
     * 账务冻结
     *
     * @param freezeBO        账务冻结单
     * @return                  true:冻结成功;false:冻结失败
     */
    private void accountFreeze(FreezeBO freezeBO) {

        FreezeReqDTO freezeReqDTO = AccountRequestConverter.getFreezeReqDTOByFreezeBO(freezeBO);
        AccountRespBO freezeAccount = accountService.freeze(freezeBO.getPayNo(),
                freezeBO.getServiceCode(), freezeReqDTO);
        //状态初始化,所有单状态不做处理
        if (PayStatusEnums.INIT.getCode().equals(freezeAccount.getStatus())){
            freezeBO.setErrorCode(freezeAccount.getErrorCode());
            freezeBO.setErrorMsg(freezeAccount.getErrorMsg());
            return;
        }
        //状态初始化,所有单状态不做处理
        if (PayStatusEnums.SUCCESS.getCode().equals(freezeAccount.getStatus())){
           freezeBO.setStatus(PayStatusEnums.SUCCESS.getCode());
           freezeBO.setFreezeCode(freezeAccount.getFreezeCode());
           freezeBO.setTransDeceiptNo(freezeAccount.getReceiptNo());
           freezeBO.setTransDate(freezeAccount.getAccDate());
        }
        //冻结失败,所有单都置失败
        if (PayStatusEnums.FAIL.getCode().equals(freezeAccount.getStatus())) {
            freezeBO.setStatus(PayStatusEnums.FAIL.getCode());
            freezeBO.setErrorCode(freezeAccount.getErrorCode());
            freezeBO.setErrorMsg(freezeAccount.getErrorMsg());
        }
    }

    /**
     * 需重试接口 对内部资金单的重试（订单状态推进）
     *
     * @param freezeBO 支付订单对象
     * @return ResponseBO
     * @throws RuntimeException 出现异常时表示重试没有成功（子类方法实现中不可捕获异常）
     */
    @Override
    public ResponseBO dalInnerFundProc(FreezeBO freezeBO) throws RuntimeException {
        preDalInnerFund(freezeBO.getStatus(), freezeBO.getPayNo());
        log.info("冻结开始处理：{}", freezeBO);
        doExecute(freezeBO);
        log.info("冻结完成结果：{}", freezeBO);
        String freezeCode = freezeBO.getFreezeCode();
        return new ResponseBO(freezeBO.getStatus(), freezeCode, freezeBO.getErrorCode(),
                freezeBO.getErrorMsg(),
                freezeBO.getPayNo(), freezeBO.isRealFlag());
    }

}
